package com.example.uploadminio.ui;

import com.example.uploadminio.model.MinioProperties;
import com.example.uploadminio.service.ConfigManager;
import com.example.uploadminio.service.FileWatcher;
import com.example.uploadminio.service.MinioUploader;
import com.example.uploadminio.service.StartupManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.awt.*;
import java.io.File;
import java.nio.file.Path;

public class MainFrame extends JFrame {
    private static final Logger log = LoggerFactory.getLogger(MainFrame.class);
    private static final String APP_NAME = "UploadMinioTool";

    private final JTextField dirField = new JTextField();
    private final JTextField endpointField = new JTextField();
    private final JTextField accessKeyField = new JTextField();
    private final JPasswordField secretKeyField = new JPasswordField();
    private final JTextField bucketField = new JTextField();
    private final JTextField bucketPrefixField = new JTextField();
    private final JTextField scanIntervalField = new JTextField("60");
    private final JCheckBox autoStartBox = new JCheckBox("开机自启");
    private final JCheckBox autoWatchBox = new JCheckBox("自动监听");

    // 日志区
    private final JTextArea logArea = new JTextArea();
    // 新增：进度区
    private final JTextArea progressArea = new JTextArea();

    private MinioProperties cfg;
    private Thread watchThread;
    private FileWatcher watcher;

    public MainFrame() {
        setTitle("文件上传工具");
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        setSize(720, 600);
        setLocationRelativeTo(null);

        cfg = ConfigManager.load();
        initUI();
        bindConfigToUI();
        // 自动监听
        if (cfg.getAutoWatch() != null && cfg.getAutoWatch()) {
            SwingUtilities.invokeLater(this::startWatching);
        }
    }

    private void initUI() {
        JPanel root = new JPanel(new BorderLayout(8, 8));
        root.setBorder(new EmptyBorder(10, 10, 10, 10));
        setContentPane(root);

        JPanel form = new JPanel(new GridBagLayout());
        GridBagConstraints gc = new GridBagConstraints();
        gc.insets = new Insets(5, 5, 5, 5);
        gc.fill = GridBagConstraints.HORIZONTAL;
        gc.gridx = 0;
        gc.gridy = 0;

        form.add(new JLabel("监听目录:"), gc);
        gc.gridx = 1;
        gc.weightx = 1;
        form.add(dirField, gc);
        JButton chooseBtn = new JButton("选择...");
        chooseBtn.addActionListener(e -> chooseDir());
        gc.gridx = 2;
        gc.weightx = 0;
        form.add(chooseBtn, gc);

        gc.gridy++;
        gc.gridx = 0;
        form.add(new JLabel("上传节点:"), gc);
        gc.gridx = 1;
        gc.gridwidth = 2;
        form.add(endpointField, gc);
        gc.gridwidth = 1;

        gc.gridy++;
        gc.gridx = 0;
        form.add(new JLabel("账号:"), gc);
        gc.gridx = 1;
        gc.gridwidth = 2;
        form.add(accessKeyField, gc);
        gc.gridwidth = 1;

        gc.gridy++;
        gc.gridx = 0;
        form.add(new JLabel("密码:"), gc);
        gc.gridx = 1;
        gc.gridwidth = 2;
        form.add(secretKeyField, gc);
        gc.gridwidth = 1;

        gc.gridy++;
        gc.gridx = 0;
        form.add(new JLabel("上传位置 (bucket):"), gc);
        gc.gridx = 1;
        gc.gridwidth = 2;
        form.add(bucketField, gc);
        gc.gridwidth = 1;

        gc.gridy++;
        gc.gridx = 0;
        form.add(new JLabel("具体位置 (folder/folder):"), gc);
        gc.gridx = 1;
        gc.gridwidth = 2;
        form.add(bucketPrefixField, gc);
        gc.gridwidth = 1;

        gc.gridy++;
        gc.gridx = 0;
        form.add(new JLabel("扫描频率（/分钟）:"), gc);
        gc.gridx = 1;
        gc.gridwidth = 2;
        form.add(scanIntervalField, gc);
        gc.gridwidth = 1;

        gc.gridy++;
        gc.gridx = 1;
        form.add(autoStartBox, gc);
        gc.gridy++;
        gc.gridx = 1;
        form.add(autoWatchBox, gc);

        JPanel buttons = new JPanel(new FlowLayout(FlowLayout.RIGHT));
        JButton saveBtn = new JButton("保存配置");
        JButton startBtn = new JButton("启动监听");
        JButton stopBtn = new JButton("停止监听");
        JButton nowBtn = new JButton("立即扫描上传");

        saveBtn.addActionListener(e -> saveConfig());
        startBtn.addActionListener(e -> startWatching());
        stopBtn.addActionListener(e -> stopWatching());
        nowBtn.addActionListener(e -> nowWatching());

        buttons.add(saveBtn);
        buttons.add(startBtn);
        buttons.add(stopBtn);
        buttons.add(nowBtn);

        // 日志区
        logArea.setEditable(false);
        logArea.setLineWrap(true);
        logArea.setWrapStyleWord(true);
        JScrollPane logScroll = new JScrollPane(logArea);

        // 新增：进度区
        progressArea.setEditable(false);
        progressArea.setLineWrap(true);
        progressArea.setWrapStyleWord(true);
        progressArea.setBackground(new Color(230, 250, 230));  // 淡绿色背景区分进度
        progressArea.setFont(new Font("Dialog", Font.PLAIN, 13));
        progressArea.setPreferredSize(new Dimension(700, 80));
        JScrollPane progressScroll = new JScrollPane(progressArea);

        // 在底部增加一个面板，放置按钮和进度区
        JPanel bottomPanel = new JPanel(new BorderLayout(8, 8));
        bottomPanel.add(progressScroll, BorderLayout.CENTER);
        bottomPanel.add(buttons, BorderLayout.SOUTH);

        root.add(form, BorderLayout.NORTH);
        root.add(logScroll, BorderLayout.CENTER);
        root.add(bottomPanel, BorderLayout.SOUTH);
    }

    private void bindConfigToUI() {
        dirField.setText(cfg.getWatchDir());
        endpointField.setText(cfg.getEndpoint());
        accessKeyField.setText(cfg.getAccessKey());
        secretKeyField.setText(cfg.getSecretKey());
        bucketField.setText(cfg.getBucket());
        bucketPrefixField.setText(cfg.getBucketPrefix());
        scanIntervalField.setText(String.valueOf(cfg.getScanInterval()));
        autoStartBox.setSelected(cfg.getAutoStart());
        autoWatchBox.setSelected(cfg.getAutoWatch());
    }

    private void collectUIToConfig() {
        cfg.setWatchDir(dirField.getText().trim());
        cfg.setEndpoint(endpointField.getText().trim());
        cfg.setAccessKey(accessKeyField.getText().trim());
        cfg.setSecretKey(new String(secretKeyField.getPassword()));
        cfg.setBucket(bucketField.getText().trim());
        cfg.setBucketPrefix(bucketPrefixField.getText().trim());
        cfg.setScanInterval(Integer.parseInt(scanIntervalField.getText().trim()));
        cfg.setAutoStart(autoStartBox.isSelected());
        cfg.setAutoWatch(autoWatchBox.isSelected());
    }

    private void chooseDir() {
        JFileChooser chooser = new JFileChooser();
        chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
        if (!dirField.getText().isBlank()) {
            File preset = new File(dirField.getText().trim());
            if (preset.exists()) chooser.setCurrentDirectory(preset);
        }
        int r = chooser.showOpenDialog(this);
        if (r == JFileChooser.APPROVE_OPTION) {
            dirField.setText(chooser.getSelectedFile().getAbsolutePath());
        }
    }

    private void saveConfig() {
        try {
            collectUIToConfig();
            ConfigManager.save(cfg);

            // 处理开机自启
            if (cfg.getAutoStart()) {
                String exePath = getRunningExecutablePath();
                StartupManager.enable(APP_NAME, exePath);
            } else {
                StartupManager.disable(APP_NAME);
            }
            info("配置已保存到: " + ConfigManager.getConfigPath());
        } catch (Exception e) {
            error("保存配置失败: " + e.getMessage());
        }
    }

    private void startWatching() {
        try {
            collectUIToConfig();
            if (cfg.getWatchDir() == null || cfg.getWatchDir().isBlank()) {
                JOptionPane.showMessageDialog(this, "请先选择监听目录", "提示", JOptionPane.WARNING_MESSAGE);
                return;
            }
            if (cfg.getBucket() == null || cfg.getBucket().isBlank()) {
                JOptionPane.showMessageDialog(this, "请先选择上传至服务器目录", "提示", JOptionPane.WARNING_MESSAGE);
                return;
            }
            ConfigManager.save(cfg);

            stopWatching(); // 防重复

            MinioUploader uploader = new MinioUploader(cfg);
            // 修改：传递 progressArea 给 FileWatcher
            watcher = new FileWatcher(Path.of(cfg.getWatchDir()), uploader, logArea, progressArea);
            watchThread = new Thread(watcher, "watcher-thread");
            watchThread.setDaemon(true);
            watchThread.start();

            info("开始监听目录: " + cfg.getWatchDir());
        } catch (Exception e) {
            error("启动监听失败: " + e.getMessage());
        }
    }

    private void nowWatching() {
        try {
            collectUIToConfig();
            if (cfg.getWatchDir() == null || cfg.getWatchDir().isBlank()) {
                JOptionPane.showMessageDialog(this, "请先选择监听目录", "提示", JOptionPane.WARNING_MESSAGE);
                return;
            }
            if (cfg.getBucket() == null || cfg.getBucket().isBlank()) {
                JOptionPane.showMessageDialog(this, "请先选择上传至服务器目录", "提示", JOptionPane.WARNING_MESSAGE);
                return;
            }
            ConfigManager.save(cfg);

            stopWatching(); // 防重复

            MinioUploader uploader = new MinioUploader(cfg);
            // 修改：传递 progressArea 给 FileWatcher
            watcher = new FileWatcher(Path.of(cfg.getWatchDir()), uploader, logArea, progressArea);
            watchThread = new Thread(watcher, "watcher-thread");
            watchThread.setDaemon(true);
            watchThread.start();

            info("立即开始扫描目录: " + cfg.getWatchDir());
        } catch (Exception e) {
            error("启动监听失败: " + e.getMessage());
        }
    }

    private void stopWatching() {
        if (watcher != null) {
            watcher.stop();
            watcher = null;
        }
        if (watchThread != null) {
            watchThread.interrupt();
            watchThread = null;
        }
        info("监听已停止");
    }

    private void info(String msg) {
        log.info(msg);
        logArea.append("[INFO] " + msg + "\n");
        logArea.setCaretPosition(logArea.getDocument().getLength());
    }

    private void error(String msg) {
        log.error(msg);
        logArea.append("[ERROR] " + msg + "\n");
        logArea.setCaretPosition(logArea.getDocument().getLength());
    }

    private String getRunningExecutablePath() {
        try {
            String p = new File(MainFrame.class.getProtectionDomain()
                    .getCodeSource().getLocation().toURI()).getAbsolutePath();
            if (p.endsWith(".exe")) return p;
        } catch (Exception ignored) {
        }
        return System.getProperty("java.class.path");
    }
}
